﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StackExchange.Redis;
using WMS.Common.DB;
using WMS.Service.Redis;

namespace WMS.Extensions
{

    public static class CacheSetup
    {
        public static IServiceCollection AddRedisCache(this IServiceCollection services, IConfiguration configuration)
        {
            RedisConfig? redisConfig = configuration.GetSection("RedisConfig").Get<RedisConfig>();

            if (redisConfig == null)
            {
                // 可以根据需要决定是否抛出异常
                throw new InvalidOperationException("RedisConfig section is missing in configuration");
                //return services; // 或者静默返回，不注册 Redis 服务
            }

            // 注册 RedisConfig 配置对象
            services.AddSingleton(redisConfig);

            // 注册 ConnectionMultiplexer 为单例
            services.AddSingleton<IConnectionMultiplexer>(sp =>
            {
                var configurationOptions = ConfigurationOptions.Parse(redisConfig.Connection);//解析连接字符串
                configurationOptions.AbortOnConnectFail = false;//连接失败时不立即抛出异常，允许重试
                configurationOptions.ConnectTimeout = redisConfig.ConnectTimeout;//建立连接的超时时间
                configurationOptions.SyncTimeout = redisConfig.SyncTimeout;//Redis 命令执行的超时时间
                configurationOptions.ReconnectRetryPolicy = new ExponentialRetry(1000);//指数退避重试策略，基准1秒
                //密码
                if (!string.IsNullOrEmpty(redisConfig.Password))
                {
                    configurationOptions.Password = redisConfig.Password;
                }
                //ConnectionMultiplexer：Redis 连接多路复用器（核心组件）
                var multiplexer = ConnectionMultiplexer.Connect(configurationOptions);

                // IHostApplicationLifetime：应用程序生命周期服务
                //ApplicationStopping：应用停止时触发的事件
                //作用：注册回调函数，在应用关闭时正确释放 Redis 连接资源
                var lifetime = sp.GetRequiredService<IHostApplicationLifetime>();
                lifetime.ApplicationStopping.Register(() =>
                {
                    multiplexer.Close();
                    multiplexer.Dispose();
                });

                return multiplexer;
            });

            // 注册 IDatabase
            services.AddSingleton<IDatabase>(sp =>
            {
                var multiplexer = sp.GetRequiredService<IConnectionMultiplexer>();
                return multiplexer.GetDatabase(redisConfig.DefaultDatabase);
            });

            //注册 Redis 服务类
            services.AddScoped<IRedisService, RedisService>();

            return services;
        }
    }
}
